#include <iostream>

#include <cstdio>

#include <unistd.h>
#include <sys/time.h>
#include <arpa/inet.h>

#include "tcp_endpoint.h"
#include "net_context.h"

using namespace usnet;

const char* LOCAL_ADDR      { "10.1.1.8" };
const char* REMOTE_ADDR     { "10.1.1.7" };
const uint16_t LOCAL_PORT   { 6789 };
const uint16_t REMOTE_PORT  { 6789 };

int main(int argc, char* argv[])
{
    if (NetContext::Init() == false) {
        std::cerr << "failed to init usnet context" << std::endl;
        return -1;
    }
    std::cout << "NetContext initialized" << std::endl;
    struct sockaddr_in laddr;
    if (inet_pton(AF_INET, LOCAL_ADDR, &laddr.sin_addr) != 1) {
        std::cerr << "failed to convert address: " << LOCAL_ADDR << std::endl;
        return -1;
    }
    laddr.sin_port = htons(LOCAL_PORT);
    struct sockaddr_in raddr;
    if (inet_pton(AF_INET, REMOTE_ADDR, &raddr.sin_addr) != 1) {
        std::cerr << "failed to convert address: " << REMOTE_ADDR << std::endl;
        return -1;
    }
    raddr.sin_port = htons(REMOTE_PORT);
    TCPEndpoint lep { laddr };
    TCPEndpoint rep { raddr };
    int connfd = lep.Connect(&rep);
    if (connfd < 0) {
        std::cerr << "failed to connect remote endpoint" << std::endl;
        return -1;
    }
    std::cout << "TCP connection established: fd = " << connfd << std::endl;

    std::cout << "Please input message:" << std::endl;
    char buf[1 << 20];
    int recv_len { 0 };
    int send_len { 0 };
    struct timeval tick;
    struct timeval tock;
    while (true) {
        memset(buf, 0, sizeof(buf));
        scanf("%s", buf);
        gettimeofday(&tick, nullptr);
        while ((send_len = lep.Send(connfd, buf, strlen(buf)) == 0));
        while ((recv_len = lep.Recv(connfd, buf, send_len) == 0));
        gettimeofday(&tock ,nullptr);
        printf("%s\n", buf);
        std::cout << "round trip time = "
                  << (tock.tv_sec - tick.tv_sec) * 1000000 + (tock.tv_usec - tick.tv_usec)
                  << std::endl;
    }

    return 0;
}